{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "Created on Feb 4, 2011\n",
    "Tree-Based Regression Methods\n",
    "@author: Peter Harrington\n",
    "'''\n",
    "from numpy import *\n",
    "\n",
    "\n",
    "def loadDataSet(fileName):  #general function to parse tab -delimited floats\n",
    "    dataMat = []  #assume last column is target value\n",
    "    fr = open(fileName)\n",
    "    for line in fr.readlines():\n",
    "        curLine = line.strip().split('\\t')\n",
    "        for i in range(len(curLine)):\n",
    "            curLine[i] = float(curLine[i])\n",
    "        dataMat.append(curLine)\n",
    "    return dataMat\n",
    "\n",
    "\n",
    "def binSplitDataSet(dataSet, feature, value):\n",
    "    mat0 = dataSet[nonzero(dataSet[:, feature] > value)[0], :][0]\n",
    "    mat1 = dataSet[nonzero(dataSet[:, feature] <= value)[0], :][0]\n",
    "    return mat0, mat1\n",
    "\n",
    "\n",
    "def regLeaf(dataSet):  #returns the value used for each leaf\n",
    "    return mean(dataSet[:, -1])\n",
    "\n",
    "\n",
    "def regErr(dataSet):\n",
    "    return var(dataSet[:, -1]) * shape(dataSet)[0]\n",
    "\n",
    "\n",
    "def linearSolve(dataSet):  #helper function used in two places\n",
    "    m, n = shape(dataSet)\n",
    "    X = mat(ones((m, n)))\n",
    "    Y = mat(ones((m, 1)))  #create a copy of data with 1 in 0th postion\n",
    "    X[:, 1:n] = dataSet[:, 0:n - 1]\n",
    "    Y = dataSet[:, -1]  #and strip out Y\n",
    "    xTx = X.T * X\n",
    "    if linalg.det(xTx) == 0.0:\n",
    "        raise NameError('This matrix is singular, cannot do inverse,\\n\\\n",
    "        try increasing the second value of ops')\n",
    "    ws = xTx.I * (X.T * Y)\n",
    "    return ws, X, Y\n",
    "\n",
    "\n",
    "def modelLeaf(dataSet):  #create linear model and return coeficients\n",
    "    ws, X, Y = linearSolve(dataSet)\n",
    "    return ws\n",
    "\n",
    "\n",
    "def modelErr(dataSet):\n",
    "    ws, X, Y = linearSolve(dataSet)\n",
    "    yHat = X * ws\n",
    "    return sum(power(Y - yHat, 2))\n",
    "\n",
    "\n",
    "def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):\n",
    "    tolS = ops[0]\n",
    "    tolN = ops[1]\n",
    "    #if all the target variables are the same value: quit and return value\n",
    "    if len(set(dataSet[:, -1].T.A.tolist()[0])) == 1:  #exit cond 1\n",
    "        print('1111111')\n",
    "        return None, leafType(dataSet)\n",
    "    m, n = shape(dataSet)\n",
    "    #the choice of the best feature is driven by Reduction in RSS error from mean\n",
    "    S = errType(dataSet)\n",
    "    bestS = inf\n",
    "    bestIndex = 0\n",
    "    bestValue = 0\n",
    "    for featIndex in range(n - 1):\n",
    "        for splitVal in unique(dataSet[:, featIndex]):\n",
    "            mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal)\n",
    "            if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): continue\n",
    "            newS = errType(mat0) + errType(mat1)\n",
    "            if newS < bestS:\n",
    "                bestIndex = featIndex\n",
    "                bestValue = splitVal\n",
    "                bestS = newS\n",
    "    #if the decrease (S-bestS) is less than a threshold don't do the split\n",
    "    if (S - bestS) < tolS:\n",
    "        print('tolS=', tolS)\n",
    "        print('2222222')\n",
    "        return None, leafType(dataSet)  #exit cond 2\n",
    "    mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)\n",
    "    if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN):  #exit cond 3\n",
    "        print('3333333')\n",
    "        return None, leafType(dataSet)\n",
    "    return bestIndex, bestValue  #returns the best feature to split on\n",
    "    #and the value used for that split\n",
    "\n",
    "\n",
    "def createTree(\n",
    "    dataSet,\n",
    "    leafType=regLeaf,\n",
    "    errType=regErr,\n",
    "    ops=(0, 4)):  #assume dataSet is NumPy Mat so we can array filtering\n",
    "    feat, val = chooseBestSplit(dataSet, leafType, errType,\n",
    "                                ops)  #choose the best split\n",
    "\n",
    "    print('feat, val=', feat, val)\n",
    "    if feat == None:\n",
    "        return val  #if the splitting hit a stop condition return val\n",
    "    retTree = {}\n",
    "    retTree['spInd'] = feat\n",
    "    retTree['spVal'] = val\n",
    "    lSet, rSet = binSplitDataSet(dataSet, feat, val)\n",
    "    retTree['left'] = createTree(lSet, leafType, errType, ops)\n",
    "    retTree['right'] = createTree(rSet, leafType, errType, ops)\n",
    "    return retTree\n",
    "\n",
    "\n",
    "def isTree(obj):\n",
    "    return (type(obj).__name__ == 'dict')\n",
    "\n",
    "\n",
    "def getMean(tree):\n",
    "    if isTree(tree['right']): tree['right'] = getMean(tree['right'])\n",
    "    if isTree(tree['left']): tree['left'] = getMean(tree['left'])\n",
    "    return (tree['left'] + tree['right']) / 2.0\n",
    "\n",
    "\n",
    "def prune(tree, testData):\n",
    "    if shape(testData)[0] == 0:\n",
    "        return getMean(tree)  #if we have no test data collapse the tree\n",
    "    if (isTree(tree['right']) or isTree(\n",
    "            tree['left'])):  #if the branches are not trees try to prune them\n",
    "        lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal'])\n",
    "    if isTree(tree['left']): tree['left'] = prune(tree['left'], lSet)\n",
    "    if isTree(tree['right']): tree['right'] = prune(tree['right'], rSet)\n",
    "    #if they are now both leafs, see if we can merge them\n",
    "    if not isTree(tree['left']) and not isTree(tree['right']):\n",
    "        lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal'])\n",
    "        errorNoMerge = sum(power(lSet[:,-1] - tree['left'],2)) +\\\n",
    "            sum(power(rSet[:,-1] - tree['right'],2))\n",
    "        treeMean = (tree['left'] + tree['right']) / 2.0\n",
    "        errorMerge = sum(power(testData[:, -1] - treeMean, 2))\n",
    "        if errorMerge < errorNoMerge:\n",
    "            print(\"merging\")\n",
    "            return treeMean\n",
    "        else:\n",
    "            return tree\n",
    "    else:\n",
    "        return tree\n",
    "\n",
    "\n",
    "def regTreeEval(model, inDat):\n",
    "    return float(model)\n",
    "\n",
    "\n",
    "def modelTreeEval(model, inDat):\n",
    "    n = shape(inDat)[1]\n",
    "    X = mat(ones((1, n + 1)))\n",
    "    X[:, 1:n + 1] = inDat\n",
    "    return float(X * model)\n",
    "\n",
    "\n",
    "def treeForeCast(tree, inData, modelEval=regTreeEval):\n",
    "    if not isTree(tree): return modelEval(tree, inData)\n",
    "    if inData[tree['spInd']] > tree['spVal']:\n",
    "        if isTree(tree['left']):\n",
    "            return treeForeCast(tree['left'], inData, modelEval)\n",
    "        else:\n",
    "            return modelEval(tree['left'], inData)\n",
    "    else:\n",
    "        if isTree(tree['right']):\n",
    "            return treeForeCast(tree['right'], inData, modelEval)\n",
    "        else:\n",
    "            return modelEval(tree['right'], inData)\n",
    "\n",
    "\n",
    "def createForeCast(tree, testData, modelEval=regTreeEval):\n",
    "    m = len(testData)\n",
    "    yHat = mat(zeros((m, 1)))\n",
    "    for i in range(m):\n",
    "        yHat[i, 0] = treeForeCast(tree, mat(testData[i]), modelEval)\n",
    "    return yHat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1., 0., 0., 0.],\n",
       "        [0., 1., 0., 0.],\n",
       "        [0., 0., 1., 0.],\n",
       "        [0., 0., 0., 1.]])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "testMat = mat(eye(4))\n",
    "testMat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(matrix([[0., 1., 0., 0.]]), matrix([[1., 0., 0., 0.]]))"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mat0, mat1 = binSplitDataSet(testMat, 1, 0.5)\n",
    "mat0, mat1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 3.609800e-02,  1.550960e-01],\n",
       "        [ 9.933490e-01,  1.077553e+00],\n",
       "        [ 5.308970e-01,  8.934620e-01],\n",
       "        [ 7.123860e-01,  5.648580e-01],\n",
       "        [ 3.435540e-01, -3.717000e-01],\n",
       "        [ 9.801600e-02, -3.327600e-01],\n",
       "        [ 6.911150e-01,  8.343910e-01],\n",
       "        [ 9.135800e-02,  9.993500e-02],\n",
       "        [ 7.270980e-01,  1.000567e+00],\n",
       "        [ 9.519490e-01,  9.452550e-01],\n",
       "        [ 7.685960e-01,  7.602190e-01],\n",
       "        [ 5.413140e-01,  8.937480e-01],\n",
       "        [ 1.463660e-01,  3.428300e-02],\n",
       "        [ 6.731950e-01,  9.150770e-01],\n",
       "        [ 1.835100e-01,  1.848430e-01],\n",
       "        [ 3.395630e-01,  2.067830e-01],\n",
       "        [ 5.179210e-01,  1.493586e+00],\n",
       "        [ 7.037550e-01,  1.101678e+00],\n",
       "        [ 8.307000e-03,  6.997600e-02],\n",
       "        [ 2.439090e-01, -2.946700e-02],\n",
       "        [ 3.069640e-01, -1.773210e-01],\n",
       "        [ 3.649200e-02,  4.081550e-01],\n",
       "        [ 2.955110e-01,  2.882000e-03],\n",
       "        [ 8.375220e-01,  1.229373e+00],\n",
       "        [ 2.020540e-01, -8.774400e-02],\n",
       "        [ 9.193840e-01,  1.029889e+00],\n",
       "        [ 3.772010e-01, -2.435500e-01],\n",
       "        [ 8.148250e-01,  1.095206e+00],\n",
       "        [ 6.112700e-01,  9.820360e-01],\n",
       "        [ 7.224300e-02, -4.209830e-01],\n",
       "        [ 4.102300e-01,  3.317220e-01],\n",
       "        [ 8.690770e-01,  1.114825e+00],\n",
       "        [ 6.205990e-01,  1.334421e+00],\n",
       "        [ 1.011490e-01,  6.883400e-02],\n",
       "        [ 8.208020e-01,  1.325907e+00],\n",
       "        [ 5.200440e-01,  9.619830e-01],\n",
       "        [ 4.881300e-01, -9.779100e-02],\n",
       "        [ 8.198230e-01,  8.352640e-01],\n",
       "        [ 9.750220e-01,  6.735790e-01],\n",
       "        [ 9.531120e-01,  1.064690e+00],\n",
       "        [ 4.759760e-01, -1.637070e-01],\n",
       "        [ 2.731470e-01, -4.552190e-01],\n",
       "        [ 8.045860e-01,  9.240330e-01],\n",
       "        [ 7.479500e-02, -3.496920e-01],\n",
       "        [ 6.253360e-01,  6.236960e-01],\n",
       "        [ 6.562180e-01,  9.585060e-01],\n",
       "        [ 8.340780e-01,  1.010580e+00],\n",
       "        [ 7.819300e-01,  1.074488e+00],\n",
       "        [ 9.849000e-03,  5.659400e-02],\n",
       "        [ 3.022170e-01, -1.486500e-01],\n",
       "        [ 6.782870e-01,  9.077270e-01],\n",
       "        [ 1.805060e-01,  1.036760e-01],\n",
       "        [ 1.936410e-01, -3.275890e-01],\n",
       "        [ 3.434790e-01,  1.752640e-01],\n",
       "        [ 1.458090e-01,  1.369790e-01],\n",
       "        [ 9.967570e-01,  1.035533e+00],\n",
       "        [ 5.902100e-01,  1.336661e+00],\n",
       "        [ 2.380700e-01, -3.584590e-01],\n",
       "        [ 5.613620e-01,  1.070529e+00],\n",
       "        [ 3.775970e-01,  8.850500e-02],\n",
       "        [ 9.914200e-02,  2.528000e-02],\n",
       "        [ 5.395580e-01,  1.053846e+00],\n",
       "        [ 7.902400e-01,  5.332140e-01],\n",
       "        [ 2.422040e-01,  2.093590e-01],\n",
       "        [ 1.523240e-01,  1.328580e-01],\n",
       "        [ 2.526490e-01, -5.561300e-02],\n",
       "        [ 8.959300e-01,  1.077275e+00],\n",
       "        [ 1.333000e-01, -2.231430e-01],\n",
       "        [ 5.597630e-01,  1.253151e+00],\n",
       "        [ 6.436650e-01,  1.024241e+00],\n",
       "        [ 8.772410e-01,  7.970050e-01],\n",
       "        [ 6.137650e-01,  1.621091e+00],\n",
       "        [ 6.457620e-01,  1.026886e+00],\n",
       "        [ 6.513760e-01,  1.315384e+00],\n",
       "        [ 6.977180e-01,  1.212434e+00],\n",
       "        [ 7.425270e-01,  1.087056e+00],\n",
       "        [ 9.010560e-01,  1.055900e+00],\n",
       "        [ 3.623140e-01, -5.564640e-01],\n",
       "        [ 9.482680e-01,  6.318620e-01],\n",
       "        [ 2.340000e-04,  6.090300e-02],\n",
       "        [ 7.500780e-01,  9.062910e-01],\n",
       "        [ 3.254120e-01, -2.192450e-01],\n",
       "        [ 7.268280e-01,  1.017112e+00],\n",
       "        [ 3.480130e-01,  4.893900e-02],\n",
       "        [ 4.581210e-01, -6.145600e-02],\n",
       "        [ 2.807380e-01, -2.288800e-01],\n",
       "        [ 5.677040e-01,  9.690580e-01],\n",
       "        [ 7.509180e-01,  7.481040e-01],\n",
       "        [ 5.758050e-01,  8.990900e-01],\n",
       "        [ 5.079400e-01,  1.107265e+00],\n",
       "        [ 7.176900e-02, -1.109460e-01],\n",
       "        [ 5.535200e-01,  1.391273e+00],\n",
       "        [ 4.011520e-01, -1.216400e-01],\n",
       "        [ 4.066490e-01, -3.663170e-01],\n",
       "        [ 6.521210e-01,  1.004346e+00],\n",
       "        [ 3.478370e-01, -1.534050e-01],\n",
       "        [ 8.193100e-02, -2.697560e-01],\n",
       "        [ 8.216480e-01,  1.280895e+00],\n",
       "        [ 4.801400e-02,  6.449600e-02],\n",
       "        [ 1.309620e-01,  1.842410e-01],\n",
       "        [ 7.734220e-01,  1.125943e+00],\n",
       "        [ 7.896250e-01,  5.526140e-01],\n",
       "        [ 9.699400e-02,  2.271670e-01],\n",
       "        [ 6.257910e-01,  1.244731e+00],\n",
       "        [ 5.895750e-01,  1.185812e+00],\n",
       "        [ 3.231810e-01,  1.808110e-01],\n",
       "        [ 8.224430e-01,  1.086648e+00],\n",
       "        [ 3.603230e-01, -2.048300e-01],\n",
       "        [ 9.501530e-01,  1.022906e+00],\n",
       "        [ 5.275050e-01,  8.795600e-01],\n",
       "        [ 8.600490e-01,  7.174900e-01],\n",
       "        [ 7.044000e-03,  9.415000e-02],\n",
       "        [ 4.383670e-01,  3.401400e-02],\n",
       "        [ 5.745730e-01,  1.066130e+00],\n",
       "        [ 5.366890e-01,  8.672840e-01],\n",
       "        [ 7.821670e-01,  8.860490e-01],\n",
       "        [ 9.898880e-01,  7.442070e-01],\n",
       "        [ 7.614740e-01,  1.058262e+00],\n",
       "        [ 9.854250e-01,  1.227946e+00],\n",
       "        [ 1.325430e-01, -3.293720e-01],\n",
       "        [ 3.469860e-01, -1.503890e-01],\n",
       "        [ 7.687840e-01,  8.997050e-01],\n",
       "        [ 8.489210e-01,  1.170959e+00],\n",
       "        [ 4.492800e-01,  6.909800e-02],\n",
       "        [ 6.617200e-02,  5.243900e-02],\n",
       "        [ 8.137190e-01,  7.066010e-01],\n",
       "        [ 6.619230e-01,  7.670400e-01],\n",
       "        [ 5.294910e-01,  1.022206e+00],\n",
       "        [ 8.464550e-01,  7.200300e-01],\n",
       "        [ 4.486560e-01,  2.697400e-02],\n",
       "        [ 7.950720e-01,  9.657210e-01],\n",
       "        [ 1.181560e-01, -7.740900e-02],\n",
       "        [ 8.424800e-02, -1.954700e-02],\n",
       "        [ 8.458150e-01,  9.526170e-01],\n",
       "        [ 5.769460e-01,  1.234129e+00],\n",
       "        [ 7.720830e-01,  1.299018e+00],\n",
       "        [ 6.966480e-01,  8.454230e-01],\n",
       "        [ 5.950120e-01,  1.213435e+00],\n",
       "        [ 6.486750e-01,  1.287407e+00],\n",
       "        [ 8.970940e-01,  1.240209e+00],\n",
       "        [ 5.529900e-01,  1.036158e+00],\n",
       "        [ 3.329820e-01,  2.100840e-01],\n",
       "        [ 6.561500e-02, -3.069700e-01],\n",
       "        [ 2.786610e-01,  2.536280e-01],\n",
       "        [ 7.731680e-01,  1.140917e+00],\n",
       "        [ 2.036930e-01, -6.403600e-02],\n",
       "        [ 3.556880e-01, -1.193990e-01],\n",
       "        [ 9.888520e-01,  1.069062e+00],\n",
       "        [ 5.187350e-01,  1.037179e+00],\n",
       "        [ 5.145630e-01,  1.156648e+00],\n",
       "        [ 9.764140e-01,  8.629110e-01],\n",
       "        [ 9.190740e-01,  1.123413e+00],\n",
       "        [ 6.977770e-01,  8.278050e-01],\n",
       "        [ 9.280970e-01,  8.832250e-01],\n",
       "        [ 9.002720e-01,  9.968710e-01],\n",
       "        [ 3.441020e-01, -6.153900e-02],\n",
       "        [ 1.480490e-01,  2.042980e-01],\n",
       "        [ 1.300520e-01, -2.616700e-02],\n",
       "        [ 3.020010e-01,  3.171350e-01],\n",
       "        [ 3.371000e-01,  2.633200e-02],\n",
       "        [ 3.149240e-01, -1.952000e-03],\n",
       "        [ 2.696810e-01, -1.659710e-01],\n",
       "        [ 1.960050e-01, -4.884700e-02],\n",
       "        [ 1.290610e-01,  3.051070e-01],\n",
       "        [ 9.367830e-01,  1.026258e+00],\n",
       "        [ 3.055400e-01, -1.159910e-01],\n",
       "        [ 6.839210e-01,  1.414382e+00],\n",
       "        [ 6.223980e-01,  7.663300e-01],\n",
       "        [ 9.025320e-01,  8.616010e-01],\n",
       "        [ 7.125030e-01,  9.334900e-01],\n",
       "        [ 5.900620e-01,  7.055310e-01],\n",
       "        [ 7.231200e-01,  1.307248e+00],\n",
       "        [ 1.882180e-01,  1.136850e-01],\n",
       "        [ 6.436010e-01,  7.825520e-01],\n",
       "        [ 5.202070e-01,  1.209557e+00],\n",
       "        [ 2.331150e-01, -3.481470e-01],\n",
       "        [ 4.656250e-01, -1.529400e-01],\n",
       "        [ 8.845120e-01,  1.117833e+00],\n",
       "        [ 6.632000e-01,  7.016340e-01],\n",
       "        [ 2.688570e-01,  7.344700e-02],\n",
       "        [ 7.292340e-01,  9.319560e-01],\n",
       "        [ 4.296640e-01, -1.886590e-01],\n",
       "        [ 7.371890e-01,  1.200781e+00],\n",
       "        [ 3.785950e-01, -2.960940e-01],\n",
       "        [ 9.301730e-01,  1.035645e+00],\n",
       "        [ 7.743010e-01,  8.367630e-01],\n",
       "        [ 2.739400e-01, -8.571300e-02],\n",
       "        [ 8.244420e-01,  1.082153e+00],\n",
       "        [ 6.260110e-01,  8.405440e-01],\n",
       "        [ 6.793900e-01,  1.307217e+00],\n",
       "        [ 5.782520e-01,  9.218850e-01],\n",
       "        [ 7.855410e-01,  1.165296e+00],\n",
       "        [ 5.974090e-01,  9.747700e-01],\n",
       "        [ 1.408300e-02, -1.325250e-01],\n",
       "        [ 6.638700e-01,  1.187129e+00],\n",
       "        [ 5.523810e-01,  1.369630e+00],\n",
       "        [ 6.838860e-01,  9.999850e-01],\n",
       "        [ 2.103340e-01, -6.899000e-03],\n",
       "        [ 6.045290e-01,  1.212685e+00],\n",
       "        [ 2.507440e-01,  4.629700e-02]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myDat = loadDataSet('ex00.txt')\n",
    "myMat = mat(myDat)\n",
    "myMat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tolS= 0\n",
      "2222222\n",
      "feat, val= None 0.571743005\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.571743005"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "regTrees = createTree(myMat)\n",
    "regTrees"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def linearSolve(dataSet):  #helper function used in two places\n",
    "    m, n = shape(dataSet)\n",
    "    X = mat(ones((m, n)))\n",
    "    Y = mat(ones((m, 1)))  #create a copy of data with 1 in 0th postion\n",
    "    X[:, 1:n] = dataSet[:, 0:n - 1]\n",
    "    Y = dataSet[:, -1]  #and strip out Y\n",
    "    xTx = X.T * X\n",
    "    if linalg.det(xTx) == 0.0:\n",
    "        raise NameError('This matrix is singular, cannot do inverse,\\n\\\n",
    "        try increasing the second value of ops')\n",
    "    ws = xTx.I * (X.T * Y)\n",
    "    return ws, X, Y\n",
    "\n",
    "\n",
    "def modelLeaf(dataSet):  #create linear model and return coeficients\n",
    "    ws, X, Y = linearSolve(dataSet)\n",
    "    return ws\n",
    "\n",
    "\n",
    "def modelErr(dataSet):\n",
    "    ws, X, Y = linearSolve(dataSet)\n",
    "    yHat = X * ws\n",
    "    return sum(power(Y - yHat, 2))\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
